package com.jweb.framework.core.config;

import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;

import com.jweb.framework.core.Interceptor;
import com.jweb.framework.core.impl.DefaultInterceptors;


public class TopInterceptorsParser extends AbstractSingleBeanDefinitionParser {

	public static class InterceptorFactoryBean implements FactoryBean {
		
		private Interceptor interceptor ;
		
		public InterceptorFactoryBean(Interceptor interceptor){
			this.interceptor = interceptor ;
		}
		
		public Interceptor getObject() throws Exception {
			return this.interceptor ;
		}
		
		public Class getObjectType(){
			return Interceptor.class ;
		}
		
		public boolean isSingleton(){
			return true ;
		}
		
	}
	
	protected Class getBeanClass(Element element) {
		return DefaultInterceptors.class ;
	}
	
	protected void doParse(Element element , ParserContext parserContext , BeanDefinitionBuilder beanDefinitionBuilder){
		
		List list = DomUtils.getChildElementsByTagName(element , "interceptor");
		ManagedList managedList = new ManagedList();
		Element ele ;
		
		for(Iterator it = list.iterator() ; it.hasNext() ; managedList.add(parseInterceptor(ele , parserContext))){
			ele = (Element) it.next() ;
		}
		
		String id = element.getAttribute("id");
		beanDefinitionBuilder.addConstructorArgValue(managedList);
		beanDefinitionBuilder.addConstructorArgValue(id);
		
	}
	
	protected BeanDefinition parseInterceptor(Element element , ParserContext parserContext){
		
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(InterceptorFactoryBean.class);
		String ref = element.getAttribute("ref");
		if(StringUtils.hasText(ref)){
			beanDefinitionBuilder.addConstructorArgReference(ref);
		}
		else {
			String clazz = element.getAttribute("class");
			if(StringUtils.hasText(clazz)){
				BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate().parseBeanDefinitionElement(element , beanDefinitionBuilder.getRawBeanDefinition());
				if(beanDefinitionHolder != null){
					beanDefinitionHolder = parserContext.getDelegate().decorateBeanDefinitionIfRequired(element , beanDefinitionHolder , beanDefinitionBuilder.getRawBeanDefinition());
				}
				else {
					parserContext.getReaderContext().error("cannot build interceptor", element);
				}
				
				beanDefinitionBuilder.addConstructorArgValue(beanDefinitionHolder);
			}
			else {
				parserContext.getReaderContext().error("cannot build interceptor", element);
			}
		}
		
		return beanDefinitionBuilder.getBeanDefinition();
	}
}
